package environment.dungeons;

import static org.junit.Assert.*;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

import org.junit.*;

import environment.Direction;
import environment.borders.*;
import environment.borders.Void;

import temperature.*;

public class RockTest {

	private Rock slipperyRock;
	private Rock nonSlipperyRock;
	private static Rock rock1;
	private static Rock rock2;
	private static Rock loneRock;
	private static Square square1;
	private static Square square2;
	private static Square square3;
	private static Square square4;
	
	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		rock1 = new Rock(true);
		rock2 = new Rock();
		loneRock = new Rock();
		square1 = new NormalSquare(new Temperature(new BigDecimal(100), TemperatureUnit.CELSIUS), new BigDecimal(0));
		square2 = new NormalSquare(new Temperature(new BigDecimal(200), TemperatureUnit.CELSIUS), new BigDecimal(0));
		square3 = new NormalSquare(new Temperature(new BigDecimal(1000), TemperatureUnit.CELSIUS), new BigDecimal(0));
		square4 = new NormalSquare();
		rock1.setStateUsed();
		rock2.setStateUsed();
		loneRock.setStateUsed();
		square1.setStateUsed();
		square2.setStateUsed();
		square3.setStateUsed();
		square4.setStateUsed();
		rock1.setNeighbourInDirection(square1, Direction.CEILING);
		rock1.setNeighbourInDirection(square4, Direction.EAST);
		rock2.setNeighbourInDirection(square2, Direction.CEILING);
		rock2.setNeighbourInDirection(square3, Direction.EAST);
	}

	@AfterClass
	public static void tearDownAfterClass() throws Exception {
	}

	@Before
	public void setUp() throws Exception {
		slipperyRock = new Rock(true);
		nonSlipperyRock = new Rock();
	}

	@After
	public void tearDown() throws Exception {
	}

	//CONSTRUCTION OF ROCKS
	
	@Test
	public void constructor() {
		assertTrue(slipperyRock.getTemperature().equals(Temperature.CELSIUS_0));
		assertTrue(slipperyRock.getHumidity().equals(BigDecimal.ZERO));
		assertTrue(nonSlipperyRock.getTemperature().equals(Temperature.CELSIUS_0));
		assertTrue(nonSlipperyRock.getHumidity().equals(BigDecimal.ZERO));
		for(Direction direction: Direction.values()) {
			if(! (slipperyRock.getBorderAt(direction) instanceof Wall) ||
					(! (nonSlipperyRock.getBorderAt(direction) instanceof Wall)))
				assert false;
			if(! (((Wall)slipperyRock.getBorderAt(direction)).isSlippery()) ||
					(((Wall)nonSlipperyRock.getBorderAt(direction)).isSlippery()))
				assert false;
		}
	}
	
	//TEMPERATURE
	
	@Test
	public void canHaveAsTemperature_True1() {
		assertTrue(rock1.canHaveAsTemperature(rock1.calcTemperature()));
		
	}
	
	@Test
	public void canHaveAsTemperature_True2() {
		assertTrue(slipperyRock.canHaveAsTemperature(Temperature.CELSIUS_0));
		
	}
	
	@Test
	public void canHaveAsTemperature_False() {
		assertTrue(! rock1.canHaveAsTemperature(Temperature.CELSIUS_0));
	}
	
	@Test
	public void canHaveAsTemperature_Terminated() {
		slipperyRock.terminate();
		assertTrue(! slipperyRock.canHaveAsTemperature(Temperature.CELSIUS_0));
	}
	
	@Test
	public void calcTemperature() {
		assertTrue(rock1.calcTemperature().equals(new Temperature(new BigDecimal(50), TemperatureUnit.CELSIUS)));
		assertTrue(rock2.calcTemperature().equals(new Temperature(new BigDecimal(600), TemperatureUnit.CELSIUS)));
		assertTrue(loneRock.calcTemperature().equals(Temperature.CELSIUS_0));
	}
	
	//BORDERS
	
	@Test
	public void canHaveAsBorders_Wall() {
		Map<Direction, Border> newBorders = new HashMap<Direction, Border>();
		newBorders.put(Direction.NORTH, new Wall(false));
		newBorders.put(Direction.EAST, new Wall(false));
		assertTrue(rock1.canHaveAsBorders(newBorders));
	}
	
	@Test
	public void canHaveAsBorders_Door1() {
		Map<Direction, Border> newBorders = new HashMap<Direction, Border>();
		newBorders.put(Direction.NORTH, new Door(false));
		assertTrue(! rock1.canHaveAsBorders(newBorders));
	}
	
	@Test
	public void canHaveAsBorders_Door2() {
		Map<Direction, Border> newBorders = new HashMap<Direction, Border>();
		newBorders.put(Direction.EAST, new Door(false));
		assertTrue(! rock1.canHaveAsBorders(newBorders));
	}
	
	@Test
	public void canHaveAsBorders_Void() {
		Map<Direction, Border> newBorders = new HashMap<Direction, Border>();
		newBorders.put(Direction.NORTH, new Void());
		assertTrue(! rock1.canHaveAsBorders(newBorders));
	}
	
	@Test
	public void canHaveAsBorders_Terminated() {
		Map<Direction, Border> newBorders = new HashMap<Direction, Border>();
		newBorders.put(Direction.NORTH, new Wall(false));
		slipperyRock.terminate();
		assertTrue(! slipperyRock.canHaveAsBorders(newBorders));
	}
}
